/*
 * Copyright (c) 2006-2018, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2021-07-05     laowang   first version
 */

#include <rtthread.h>
#include <rtdevice.h>
#include <board.h>
#include <fal.h>
/* 添加文件系统头文件 */
#include <dfs_fs.h>
#include <tcp_transparent.h>
#include <udp_transparent.h>
#include "setting.h"
#include "ec600.h"
#include "esp8266.h"
#include "led.h"
#include "rs232.h"
#include "rs485.h"
#include "tcp2rtu.h"
#include "mqtt2rtu.h"
#include "w5500_dev.h"
#include <arpa/inet.h>         /* 包含 ip_addr_t 等地址相关的头文件 */
#include <netdev.h>            /* 包含全部的 netdev 相关操作接口函数 */
#include "vconsole.h"

/* 定义要使用的分区名字 */
#define FS_PARTITION_NAME              "filesystem"

/* 添加 DEBUG 头文件 */
#define DBG_SECTION_NAME               "main"
#define DBG_LEVEL                      DBG_INFO
#include <rtdbg.h>
/* 定义要使用的分区名字 */

extern device_param_t device_setting;

void check_netdev(void)
{
    //获取网卡
    struct netdev *first_netdev = RT_NULL;
    first_netdev = netdev_get_first_by_flags(NETDEV_FLAG_LINK_UP);
    while(first_netdev == RT_NULL || first_netdev->ip_addr.addr == 0)
    {
        rt_thread_mdelay(1000);
        //rt_kprintf("Netdev get first by linkup failed!\n");
        first_netdev = netdev_get_first_by_flags(NETDEV_FLAG_LINK_UP);
    }
    led_run_set_mode(LED_RUN_MODE_LINK_UP);
    if(device_setting->netdev_params.netdev_type == NETDEV_TYPE_W5500 || device_setting->netdev_params.netdev_type == NETDEV_TYPE_ESP8266)
    {
        //设置dhcp
        netdev_dhcp_enabled(first_netdev, device_setting->netdev_params.dhcp);
        if(!device_setting->netdev_params.dhcp)
        {
            /* 设置网卡 IP 地址 */
            netdev_set_ipaddr(first_netdev, &device_setting->netdev_params.ip_addr);
            /* 设置网卡网关地址 */
            netdev_set_gw(first_netdev, &device_setting->netdev_params.gw);
            /* 设置网卡子网掩码地址 */
            netdev_set_netmask(first_netdev, &device_setting->netdev_params.netmask);
            /* 设置网卡 DNS1 服务器地址 */
            netdev_set_dns_server(first_netdev, 0, &device_setting->netdev_params.dns_servers[0]);
            /* 设置网卡 DNS2 服务器地址 */
            netdev_set_dns_server(first_netdev, 1, &device_setting->netdev_params.dns_servers[1]);
        }
    }
}

int main(void)
{
    struct rt_device *mtd_dev = RT_NULL;
    //初始化fal
    fal_init();
    /* 生成 mtd 设备 */
    mtd_dev = fal_mtd_nor_device_create(FS_PARTITION_NAME);
    if (!mtd_dev)
    {
        LOG_E("Can't create a mtd device on '%s' partition.", FS_PARTITION_NAME);
    }
    else
    {
        /* 挂载 littlefs */
        if (dfs_mount(FS_PARTITION_NAME, "/", "lfs", 0, 0) == 0)
        {
            LOG_I("Filesystem initialized!");
        }
        else
        {
            /* 格式化文件系统 */
            dfs_mkfs("lfs", FS_PARTITION_NAME);
            /* 挂载 littlefs */
            if (dfs_mount("filesystem", "/", "lfs", 0, 0) == 0)
            {
                LOG_I("Filesystem initialized!");
            }
            else
            {
                LOG_E("Failed to initialize filesystem!");
            }
        }
    }
    //初始化led
    led_init();
    //初始化配置
    setting_init();
    //初始化网卡
    switch (device_setting->netdev_params.netdev_type)
    {
        case NETDEV_TYPE_EC600:
        {
            ec200x_device_register();
            break;
        }
        case NETDEV_TYPE_W5500:
            w5500_device_register();
            break;
        case NETDEV_TYPE_ESP8266:
        {
            esp8266_device_register();
            break;
        }
        default:
            break;
    }
    //配置网卡
    check_netdev();
    //初始化功能
    switch(device_setting->fun_type)
    {
        case FUN_TYPE_TCP_TRANSPARENT:
        {
            if(device_setting->down_dev == 0)
            {
                rs232_init(tcp_transparent_send);
                tcp_transparent_init(rs232_send);
            }
            else if (device_setting->down_dev == 1)
            {
                rs485_init(tcp_transparent_send);
                tcp_transparent_init(rs485_send);
            }
            break;
        }
        case FUN_TYPE_UDP_TRANSPARENT:
        {
            if(device_setting->down_dev == 0)
            {
                rs232_init(udp_rransparent_send);
                udp_transparent_init(rs232_send);
            }
            else if (device_setting->down_dev == 1)
            {
                rs485_init(udp_rransparent_send);
                udp_transparent_init(rs485_send);
            }
            break;
        }
        case FUN_TYPE_TCP2RTU:
        {
            tcp2rtu_init();
            break;
        }
        case FUN_TYPE_232C485:
        {
            rs232_init(rs485_send);
            rs485_init(rs232_send);
            break;
        }
        case FUN_TYPE_MQTT2RTU:
        {
            mqtt2rtu_init();
            break;
        }
        default:
            break;
    }

    while (1)
    {
        rt_thread_mdelay(1000);
    }

    return RT_EOK;
}

static rt_device_t vcom_shell_device = NULL;
static int change_shell(void)
{
    vcom_shell_device = rt_device_find("vcom");
    if (vcom_shell_device)
    {
        vconsole_switch(vcom_shell_device);
    }
    return RT_EOK;
}
INIT_APP_EXPORT(change_shell);

/**
 * Function    ota_app_vtor_reconfig
 * Description Set Vector Table base location to the start addr of app(RT_APP_PART_ADDR).
*/
static int ota_app_vtor_reconfig(void)
{
    #define NVIC_VTOR_MASK   0x3FFFFF80
    /* Set the Vector Table base location by user application firmware definition */
    SCB->VTOR = STM32_FLASH_START_ADRESS & NVIC_VTOR_MASK;

    return 0;
}
INIT_BOARD_EXPORT(ota_app_vtor_reconfig);

